{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7a12b0f0",
   "metadata": {},
   "source": [
    "# Lesson 3: Training Models in Low Carbon Regions"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1de50c3f",
   "metadata": {},
   "source": [
    "* Import libraries to train a model locally."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "8b567f06-6dc3-429c-823a-c68f14a1171c",
   "metadata": {
    "height": 98
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "from sklearn.datasets import make_blobs\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4a3fce95",
   "metadata": {},
   "source": [
    "* Create a dataset.\n",
    "\n",
    "This is an example from the [Advanced Learning Algorithms](https://www.coursera.org/learn/advanced-learning-algorithms) course."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "47b67bc4-f6fb-410c-a9da-735c37685ee1",
   "metadata": {
    "height": 166
   },
   "outputs": [],
   "source": [
    "classes = 4\n",
    "m = 100\n",
    "centers = [[-5, 2], [-2, -2], [1, 2], [5, -2]]\n",
    "std = 1.0\n",
    "X_train, y_train = make_blobs(\n",
    "    n_samples=m, \n",
    "    centers=centers, \n",
    "    cluster_std=std,\n",
    "    random_state=30)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fcb41a9",
   "metadata": {},
   "source": [
    "* Create the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "43a4297a-cc98-47b7-95d4-703caecdccb7",
   "metadata": {
    "height": 132
   },
   "outputs": [],
   "source": [
    "# Create the model\n",
    "model = Sequential(\n",
    "    [\n",
    "        Dense(2, activation = 'relu',   name = \"L1\"),\n",
    "        Dense(4, activation = 'linear', name = \"L2\")\n",
    "    ]\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bdcb0dae-f2a5-440e-9699-64ed4e80e055",
   "metadata": {
    "height": 98
   },
   "outputs": [],
   "source": [
    "model.compile(\n",
    "    loss=tf.keras.losses.SparseCategoricalCrossentropy(\n",
    "        from_logits=True),\n",
    "    optimizer=tf.keras.optimizers.Adam(0.01),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "065a4823",
   "metadata": {},
   "source": [
    "* Train the model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7ef0d574-3899-4808-88c1-de3e551528c8",
   "metadata": {
    "height": 81
   },
   "outputs": [],
   "source": [
    "model.fit(\n",
    "    X_train,y_train,\n",
    "    epochs=200\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7916c263",
   "metadata": {},
   "source": [
    "### Running on Google Cloud\n",
    "\n",
    "We will use Google Cloud's ML platform, Vertex AI. To run this code on Vertex AI, we first need to:\n",
    "1. Import and initialize the Vertex AI Python SDK\n",
    "2. Write the ML training code to a file\n",
    "3. Configure and submit a training job that runs our training code."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ff5628f8",
   "metadata": {},
   "source": [
    "* Step 1. Initialize Vertex AI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6aa103e6-91f0-4506-b444-7af210ae0b05",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "from helper import authenticate\n",
    "CREDENTIALS, PROJECT_ID = authenticate()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "165068fa-747a-4a43-aaae-24599ec361c3",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "from google.cloud import aiplatform"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "95d98265-e5e2-4adf-9ef3-b7ab5e4dd7f7",
   "metadata": {
    "height": 64
   },
   "outputs": [],
   "source": [
    "aiplatform.init(project=PROJECT_ID,\n",
    "                credentials=CREDENTIALS,\n",
    "                )"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2205640c",
   "metadata": {},
   "source": [
    "* Step 2. Write the ML training code to a file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e6c4ad22-f843-497a-8efe-03780857be08",
   "metadata": {
    "height": 676
   },
   "outputs": [],
   "source": [
    "%%writefile task.py\n",
    "\n",
    "# import libraries\n",
    "import numpy as np\n",
    "from sklearn.datasets import make_blobs\n",
    "import tensorflow as tf\n",
    "from tensorflow.keras.models import Sequential\n",
    "from tensorflow.keras.layers import Dense\n",
    "\n",
    "# Create dataset\n",
    "classes = 4\n",
    "m = 100\n",
    "centers = [[-5, 2], [-2, -2], [1, 2], [5, -2]]\n",
    "std = 1.0\n",
    "X_train, y_train = make_blobs(\n",
    "    n_samples=m, \n",
    "    centers=centers, \n",
    "    cluster_std=std,\n",
    "    random_state=30)\n",
    "\n",
    "# Create the model\n",
    "model = Sequential(\n",
    "    [\n",
    "        Dense(2, activation = 'relu',   name = \"L1\"),\n",
    "        Dense(4, activation = 'linear', name = \"L2\")\n",
    "    ]\n",
    ")\n",
    "\n",
    "model.compile(\n",
    "    loss=tf.keras.losses.SparseCategoricalCrossentropy(\n",
    "        from_logits=True),\n",
    "    optimizer=tf.keras.optimizers.Adam(0.01),\n",
    ")\n",
    "\n",
    "# Train\n",
    "model.fit(\n",
    "    X_train,y_train,\n",
    "    epochs=200\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "616ceab3-02f3-49f5-88bd-b560a4a3908d",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "ls"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff21b5e4-5439-4721-a28b-109fc7230cf7",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "cat task.py"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2bfa47c",
   "metadata": {},
   "source": [
    "* Define the Custom Trainin Job."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0fbb742d",
   "metadata": {},
   "source": [
    "> Note: Check here to find more information about [Prebuilt containers for custom training](https://cloud.google.com/vertex-ai/docs/training/pre-built-containers)\n",
    "\n",
    "> Note: Check here to find more information about [Carbon free energy for Google Cloud regions](https://cloud.google.com/sustainability/region-carbon)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "06e502c7-eda6-4c10-978d-aa730731dbb7",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "# Choose a location (with carbon free energy available for this example)\n",
    "REGION = 'us-central1'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "86977ad6",
   "metadata": {},
   "source": [
    "* Create a store bucket."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "fa25f631-175d-4700-bc30-70db90cb6bcb",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "import random\n",
    "import string"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "58367b95-19e4-4e8b-a2c3-a1b0a256643e",
   "metadata": {
    "height": 132
   },
   "outputs": [],
   "source": [
    "def generate_uuid(length: int = 8) -> str:\n",
    "    return \"\".join(\n",
    "        random.choices(\n",
    "            string.ascii_lowercase + string.digits, \n",
    "            k=length))\n",
    "\n",
    "UUID = generate_uuid()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2380693a-7167-4855-b516-e2837b4b9a97",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "# The unique identifier\n",
    "UUID"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "489859f0-5299-43a2-a718-6637dc37b41a",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "from google.cloud import storage"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "986c8fd6-6558-408e-bd04-74b301842acb",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "storage_client = storage.Client(project = PROJECT_ID,\n",
    "                                credentials = CREDENTIALS)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cd33c614-ff8a-4acc-b8e1-5f7a530ab565",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "bucket_name = f'carbon-course-bucket-{UUID}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "aa46eac4-6009-4489-bc6e-ed18b2db7dff",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "bucket_name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b9377f73-662c-45fb-ada9-0b6152b7fb40",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "bucket = storage_client.bucket(bucket_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "424eb498-ecc1-43d7-8e2d-812bf272ac73",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "bucket.create(location=REGION)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "67cc2bb0-f678-4c5d-bf75-1b57911397cd",
   "metadata": {
    "height": 149
   },
   "outputs": [],
   "source": [
    "# Create the CustomTrainingJob\n",
    "job = aiplatform.CustomTrainingJob(\n",
    "    display_name='dlai-course-example',\n",
    "    script_path='task.py',\n",
    "    container_uri='us-docker.pkg.dev/vertex-ai/training/tf-cpu.2-14.py310:latest',\n",
    "    staging_bucket=f'gs://{bucket_name}',\n",
    "    location=REGION,\n",
    ")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1cc56b5d-4108-4592-a580-bc0e587f0ce7",
   "metadata": {
    "height": 30
   },
   "outputs": [],
   "source": [
    "model = job.run()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4d65abae-b35b-4818-853a-4c68a44587f8",
   "metadata": {
    "height": 47
   },
   "outputs": [],
   "source": [
    "# Delete the bucket to clean up resources\n",
    "bucket.delete(force=True)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
